/**
在TypeScript中，泛型（Generics）是一种强大的功能，它允许开发者在定义函数、类或接口时使用类型参数，从而实现类型的参数化。
  1. 泛型的基本概念
  - 泛型提供了一种在保持类型安全的同时实现代码复用的方式。通过将类型作为参数传递，可以创建适用于多种类型的函数或类。
    
  2. 泛型函数
  - 使用泛型函数可以在函数定义时指定类型参数，函数调用时根据传入的参数推断出具体的类型。
    
    例如：
  function identity<T>(arg: T): T {
        return arg;
    }

    const result1 = identity<string>("Hello, World!"); // 指定类型为字符串
    const result2 = identity(42); // 自动推断类型为数字
  3. 泛型接口
  - 泛型接口允许在接口定义中使用类型参数，从而使接口能够处理多种类型。
    
    例如：
  interface GenericIdentityFn<T> {
        (arg: T): T;
    }

    const myIdentity: GenericIdentityFn<number> = (arg) => {
        return arg;
    };

    const result = myIdentity(123); // result 为数字类型
  4. 泛型类
  - 泛型类允许在类的定义中使用类型参数，使得类能够处理不同类型的数据。
    
    例如：
  class Box<T> {
        private value: T;

        constructor(value: T) {
            this.value = value;
        }

        getValue(): T {
            return this.value;
        }
    }

    const numberBox = new Box<number>(123);
    const stringBox = new Box<string>("Hello");
  5. 多个类型参数
  - 泛型可以接受多个类型参数，以支持更复杂的类型关系。
    
    例如：
  function merge<T, U>(objA: T, objB: U): T & U {
        return { ...objA, ...objB };
    }

    const merged = merge({ name: "Alice" }, { age: 25 });
  6. 约束泛型
  - 可以对泛型类型参数设置约束，以限制其类型范围。
    
    例如：
  interface Lengthwise {
        length: number;
    }

    function logLength<T extends Lengthwise>(arg: T): void {
        console.log(arg.length);
    }

    logLength("Hello"); // 合法，字符串有length属性
  7. 总结
  泛型是TypeScript中一种强大的特性，它通过类型参数化实现了类型的灵活性和可重用性。通过使用泛型函数、接口和类，开发者可以编写出更具通用性和类型安全的代码，减少重复代码的编写，提高代码的可维护性。
 */
// 1.理解形参和实例参数化, 但是参数的类型是固定的
// function foo(name: string, age: number) {}
// foo("kobe", 30)

// 2.定义函数: 将传入的内容返回
function foo<Type>(arg: Type): Type {
  return arg;
}

// 2.1. 完整的写法
const f1 = foo<number>(123);
const f2 = foo<string>("abc");
const f3 = foo<{name: string}>({name: 'generics-name'});

// 2.2. 省略的写法
const f4 = foo(123);
const f5 = foo("abc");